package titan.wizards.newPackagedSection;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;

import titan.data.packages.PackageData;
import titan.data.packages.PackageList;
import titan.messages.Messages;
import titan.utils.FileUtils;
import titan.utils.SWTUtils;
import titan.utils.TitanUtils;
import titan.wizards.BaseTitanPage;

/**
 * At this page you can choose a package to base your section and define a name to the section.
 * Further, you can fill the package properties fields
 */
public class SectionPage extends BaseTitanPage  {
	Combo packageCombo;
	Text unixName;
	Text[] propertyText;
	Label[] propertyLabel;
	PackageList packList;
	Button infoButton;
	int maxProperties;
	private IProject project;
	private String info;
	private String sectionPath;
	private String projectPath;
	//Status
	private IStatus unixNameStatus;

	protected SectionPage() {
		super(Messages.NewSection);
		setTitle(Messages.NewSection);
		setDescription(Messages.SectionPage_desc);
		pageStatus = new Status(IStatus.OK, "default", ""); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * {@inheritDoc}
	 */
	public void createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout(4, false);
		layout.verticalSpacing = 12;
		composite.setLayout(layout);
		setControl(composite);
		GridData gd = new GridData(320, 13);

		MouseTrackAdapter mouseExit = new MouseTrackAdapter() {
			public void mouseExit(MouseEvent e) {
			    applyStatus(pageStatus);
			}
		};

		gd.horizontalSpan = 2;
		gd.horizontalAlignment = SWT.FILL;
		new Label(composite, SWT.NONE).setText(Messages.Package+":"); //$NON-NLS-1$
		packageCombo = new Combo (composite, SWT.READ_ONLY);
		for(int i = 0; i < packList.getSize(); i++)
			packageCombo.add(packList.getPackage(i).getFullName());
		packageCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				packageChanged();
			}
		});
		packageCombo.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
			    applyStatus(new Status(IStatus.INFO, "packageCombo", Messages.SelectPackage) ); //$NON-NLS-1$
			}
		});
		packageCombo.addMouseTrackListener(mouseExit);
		packageCombo.setLayoutData(gd);

	    infoButton = new Button(composite, SWT.PUSH);
		try {
			URL imageUrl = FileLocator.toFileURL( getClass().getResource("/resources/icons/info.png")); //$NON-NLS-1$
			Image image = new Image(null, imageUrl.getPath());
		    infoButton.setImage(image);
		} catch (IOException e) {
			infoButton.setText("info"); //$NON-NLS-1$
		}
		infoButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				SWTUtils.openContentDialog(getShell(), Messages.PackageInfo, info);
			}
		});

		new Label(composite, SWT.NONE).setText(Messages.UnixName+":"); //$NON-NLS-1$
		unixName = new Text(composite, SWT.BORDER | SWT.SINGLE);
		gd = new GridData();
		gd.horizontalSpan = 2;
		gd.horizontalAlignment = SWT.FILL;
		unixName.setLayoutData(gd);
		unixName.setText(packList.getPackage(0).getName());
		unixName.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				Status status = new Status(IStatus.OK, "unixName", ""); //$NON-NLS-1$ //$NON-NLS-2$
				try {
					if(!FileUtils.isEmptyFolder(sectionPath+unixName.getText()))
						status = new Status(IStatus.WARNING, "unixName", //$NON-NLS-1$
								Messages.SectFolderNEmpty+Messages.ContentWillBeReplaced);
					TitanUtils tu = new TitanUtils(projectPath);
					if(tu.existSectionInBusiness(unixName.getText()))
						status = new Status(IStatus.ERROR, "unixName", Messages.BusinessEntryTaken); //$NON-NLS-1$
				} catch (Exception e) {
					status = new Status(IStatus.ERROR, "unixName", e.getMessage()); //$NON-NLS-1$
				}
				applyStatus(status);
			}
		});
		unixName.addListener(SWT.MouseEnter, new Listener () {
			public void handleEvent(Event e) {
				applyStatus(new Status(IStatus.INFO, "unixName", Messages.SectionName_desc) ); //$NON-NLS-1$
			}
		});
		unixName.addMouseTrackListener(mouseExit);
		new Label(composite, SWT.NONE);

		propertyLabel = new Label[maxProperties];
		propertyText = new Text[maxProperties];
		for(int i = 0; i < maxProperties; i++){
			propertyLabel[i] = new Label(composite, SWT.NONE);
			propertyText[i] = new Text(composite, SWT.BORDER | SWT.SINGLE);
			gd = new GridData();
			gd.horizontalSpan = 2;
			gd.horizontalAlignment = SWT.FILL;
			propertyText[i].setLayoutData(gd);
			propertyText[i].addListener(SWT.MouseEnter, new Listener () {
				public void handleEvent(Event e) {
					if(e.widget.getData() != null)
						applyStatus(new Status(IStatus.INFO, "propertyText", //$NON-NLS-1$
							(String)(e.widget.getData()) ) );
				}
			});
			propertyText[i].addMouseTrackListener(mouseExit);
			new Label(composite, SWT.NONE);
		}
		packageCombo.select(0);
		packageChanged();
	}

	/**
	 * Method called when the package selection has changed.
	 * It displays the selected package
	 */
	protected void packageChanged() {
		int index = packageCombo.getSelectionIndex();
		PackageData packData = packList.getPackage(index);
		info = packData.getInfo();
		if(info != null)
			infoButton.setEnabled(true);
		else
			infoButton.setEnabled(false);
		unixName.setText(packData.getName());
		int length = packData.getPropertiesNumber();
		for(int i = 0; i < length; i++){
			propertyLabel[i].setVisible(true);
			propertyText[i].setVisible(true);
			propertyText[i].setData(packData.getPropertyHelp(i));
			propertyLabel[i].setText(packData.getPropertyLabel(i)+":"); //$NON-NLS-1$
			propertyText[i].setText(packData.getPropertyDefaultValue(i));
		}
		for(int i = length; i < maxProperties; i++){
			propertyText[i].setVisible(false);
			propertyLabel[i].setVisible(false);
		}
	}

	/**
	 * Try to load package list from repository directory of the project
	 * @param project - the project to load packages
	 * @throws Exception if it couldn't load packages list
	 */
	public void loadPackages(IProject project) throws Exception {
		this.project = project;
		//Get repos directory
		String reposPath = TitanUtils.getProjectProperty(project, "reposPath"); //$NON-NLS-1$
		//load package list from repos directory
		packList = new PackageList(reposPath);
		maxProperties = packList.getMaxProperties();

		//get project and section path
		projectPath = TitanUtils.getProjectProperty(project, "projectPath"); //$NON-NLS-1$
		sectionPath = projectPath+"section"+File.separator; //$NON-NLS-1$
	}

	/**
	 * Copy the selected package from repository to application section directory
	 * and modify properties to instantiate section
	 * @return true if everything went OK, false otherwise
	 */
	public boolean createSectionFromSelectedPackage() {
			try {
				//get selected package
				PackageData packData = packList.getPackage(packageCombo.getSelectionIndex());
				//get properties to write
				int length = packData.getPropertiesNumber();
				String[] propertyValues = null;
				if(length != 0) {
					propertyValues = new String[length];
					for(int j = 0; j < length; j++)
						propertyValues[j] = propertyText[j].getText();
				}
				//Copy files from selected package directory to the application's section directory and write properties
				packData.copyAndModifyProperties(sectionPath+unixName.getText(), propertyValues);
				TitanUtils tu = new TitanUtils(projectPath);
				//Add section entry to business.xml
				tu.addSectionEntry(packData.getLabel(), unixName.getText(), packData.getComponent(), "", ""); //$NON-NLS-1$ //$NON-NLS-2$
				File sql = packData.getSql();
				if(sql != null)
					tu.runSQL(sql.getAbsolutePath());
			} catch (Exception e) {
				MessageDialog.openError(getShell(), Messages.Error, e.getMessage());
				if(e.getMessage() != Messages.EntityAlExists)
					return false;
			}

			try {
				project.refreshLocal(IResource.DEPTH_INFINITE, null);
			} catch (Exception e) {
				//do nothing... unable to refresh project tree (silent fail)
			}
			return true;
	}

	/**
	 * {@inheritDoc}
	 */
	protected void applyStatus(IStatus new_status) {
		if(new_status.getSeverity() != IStatus.INFO)
			unixNameStatus = new_status;
		applyPageStatus(new_status);
	}

	/**
	 * {@inheritDoc}
	 */
	protected IStatus greaterStatus() {
		return unixNameStatus;
	}

	/**
	 * Returns whether this page is completed
	 * @return true if the wizard could be finished, and false otherwise
	 */
	public boolean canFinish() {
		if(pageStatus.getSeverity() == IStatus.ERROR || unixName.getText().isEmpty()) //$NON-NLS-1$
			return false;
		PackageData packData = packList.getPackage(packageCombo.getSelectionIndex());
		//get properties to write
		int length = packData.getPropertiesNumber();
		for(int i = 0; i < length; i++)
			if(propertyText[i].getText().isEmpty()) //$NON-NLS-1$
				return false;
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean canFlipToNextPage() {
		return false;
	}
}